//using System;
//using System.Collections.Generic;
//namespace BrainTechLLC.DAL
//{
//    /// <summary>
//    /// Provides a strongly-typed (int ID, string name, and object) mapping
//    /// </summary>
//    public class IDAndNameMapping : IDNameObjectMapping<int, string, IDAndNameMapping>
//    {
//        public IDAndNameMapping(int ky, string nam, IDAndNameMapping o) : base(ky, nam, o) { }
//    }
//    /// <summary>
//    /// Handles a simple cached list (get and invalidate)
//    /// </summary>
//    /// <typeparam name="T"></typeparam>
//    public class CachedList<T> : ICrossObjectMappingBase where T : class
//    {
//        public delegate List<T> PopulateCacheFunction();
//        private List<T> _cachedList = null;
//        private object _lockObj = new object();
//        private DateTime _lastRetrieved = DateTime.MinValue;
//        /// <summary>
//        /// Returns the cached list.  Takes a delegate that will populate a List<typeparamref name="T"/> if there is nothing in cache.
//        /// </summary>
//        /// <param name="fn"></param>
//        /// <returns></returns>
//        public List<T> GetCachedList(PopulateCacheFunction fn)
//        {
//            if (_cachedList == null || DateTime.Now.Date > _lastRetrieved.Date) { lock (_lockObj) { if (_cachedList == null || DateTime.Now.Date > _lastRetrieved.Date) { _cachedList = fn(); } } }
//            return _cachedList;
//        }
//        public void InvalidateCache() { lock (_lockObj) { _cachedList = null; } }
//    }
//    /// <summary>
//    /// Provides a quick lookup field where a single key maps to a single field (example: Quickly look up a member using their MENCID)
//    /// </summary>
//    /// <typeparam name="T1"></typeparam>
//    /// <typeparam name="T2"></typeparam>
//    public class QuickFieldLookup<T1, T2> : ICrossObjectMappingBase
//    {
//        internal Dictionary<T1, T2> _lookup = null;
//        internal object _lockObj = new object();
//        /// <summary>
//        /// Removes the mapping between a key and an old value, and adds a mapping between the key and a new value
//        /// </summary>
//        /// <param name="oldval"></param>
//        /// <param name="newval"></param>
//        /// <param name="newobj"></param>
//        public void UpdateMapping(T1 oldval, T1 newval, T2 newobj)
//        {
//            lock (_lockObj)
//            {
//                if (_lookup == null) { _lookup = new Dictionary<T1, T2>(512); }
//                if (oldval != null)
//                {
//                    // Remove the old key, if any
//                    if (_lookup.ContainsKey(oldval)) { _lookup.Remove(oldval); }
//                }
//                // Add the new/changed key
//                if (!_lookup.ContainsKey(newval)) { _lookup.Add(newval, newobj); }
//                else _lookup[newval] = newobj;
//            }
//        }
//        public bool IsEmpty { get { return (_lookup == null || _lookup.Count == 0); } }
//        /// <summary>
//        /// Invalidates the cache
//        /// </summary>
//        public void InvalidateCache() { lock (_lockObj) { _lookup = null; } }
//        /// <summary>
//        /// Adds a simple mapping between a key and a value
//        /// </summary>
//        /// <param name="key"></param>
//        /// <param name="val"></param>
//        public void AddMapping(T1 key, T2 val)
//        {
//            lock (_lockObj)
//            {
//                if (_lookup == null) { _lookup = new Dictionary<T1, T2>(512); }
//                if (!_lookup.ContainsKey(key)) { _lookup.Add(key, val); }
//            }
//        }
//        /// <summary>
//        /// Removes a key and its map to a value
//        /// </summary>
//        /// <param name="key"></param>
//        public void RemoveKey(T1 key)
//        {
//            if (_lookup != null)
//            {
//                lock (_lockObj) { if (_lookup != null) { if (_lookup.ContainsKey(key)) { _lookup.Remove(key); } } }
//            }
//        }
//        /// <summary>
//        /// Quickly looks up a value, given a key
//        /// </summary>
//        /// <param name="key"></param>
//        /// <param name="val"></param>
//        /// <returns></returns>
//        public bool PerformLookup(T1 key, ref T2 val)
//        {
//            if (_lookup != null)
//            {
//                lock (_lockObj) { if (_lookup != null) { if (!_lookup.TryGetValue(key, out val)) { return false; } else { return true; } } }
//            }
//            return false;
//        }
//    }
//    /// <summary>
//    /// A one-to-many lookup.  Example: one member ID may point to multiple teacher entries.
//    /// </summary>
//    /// <typeparam name="T1"></typeparam>
//    /// <typeparam name="T2"></typeparam>
//    public class OneToManyQuickFieldLookup<T1, T2> : ICrossObjectMappingBase
//    {
//        public Dictionary<T1, List<T2>> _lookup = null;
//        public object _lockObj = new object();
//        /// <summary>
//        /// Updates the mapping, ensuring that the key is no longer linked with the old value, but is properly
//        /// linked with the new value
//        /// </summary>
//        /// <param name="oldval"></param>
//        /// <param name="newval"></param>
//        /// <param name="newobj"></param>
//        public void UpdateMapping(T1 oldval, T1 newval, T2 newobj)
//        {
//            lock (_lockObj)
//            {
//                if (_lookup == null) { _lookup = new Dictionary<T1, List<T2>>(512); }
//                if (oldval != null)
//                {
//                    // Remove the old key, if any
//                    if (_lookup.ContainsKey(oldval)) { _lookup.Remove(oldval); }
//                }
//                // Add the new/changed key and value
//                if (!_lookup.ContainsKey(newval))
//                {
//                    List<T2> rg;
//                    rg = new List<T2>(8);
//                    rg.Add(newobj);
//                    _lookup.Add(newval, rg);
//                }
//                else
//                {
//                    List<T2> rg;
//                    if (_lookup.TryGetValue(newval, out rg) == true) { for (int i = 0; i < rg.Count; i++) { if (rg[i].Equals(newobj)) { rg.RemoveAt(i); break; } } }
//                    else
//                    {
//                        rg = new List<T2>(8);
//                        rg.Add(newobj);
//                        _lookup[newval] = rg;
//                    }
//                }
//            }
//        }
//        /// <summary>
//        /// Invalidate the cache
//        /// </summary>
//        public void InvalidateCache() { lock (_lockObj) { _lookup = null; } }
//        /// <summary>
//        /// Adds multiple mappings between a key and multiple values (adds many new teacher records to be associated with an existing member ID)
//        /// </summary>
//        /// <param name="key"></param>
//        /// <param name="newvals"></param>
//        public void AddMapping(T1 key, List<T2> newvals)
//        {
//            for (int i = 0; i < newvals.Count; i++)
//            {
//                AddMapping(key, newvals[i]);
//            }
//        }
//        /// <summary>
//        /// Adds a mapping between a key and a single value (add a new teacher record to an existing member ID)
//        /// </summary>
//        /// <param name="key"></param>
//        /// <param name="val"></param>
//        public void AddMapping(T1 key, T2 val)
//        {
//            lock (_lockObj)
//            {
//                if (_lookup == null) { _lookup = new Dictionary<T1, List<T2>>(512); }
//                if (!_lookup.ContainsKey(key))
//                {
//                    List<T2> rg = new List<T2>(8);
//                    rg.Add(val);
//                    _lookup.Add(key, rg);
//                }
//                else
//                {
//                    List<T2> rg = _lookup[key];
//                    bool fAlreadyThere = false;
//                    for (int i = 0; i < rg.Count; i++)
//                    {
//                        if (rg[i].Equals(val)) { fAlreadyThere = true; break; }
//                    }
//                    if (!fAlreadyThere) rg.Add(val);
//                }
//            }
//        }
//        /// <summary>
//        /// Removes a lookup key from the collection
//        /// </summary>
//        /// <param name="key"></param>
//        public void RemoveKey(T1 key)
//        {
//            if (_lookup != null)
//            {
//                lock (_lockObj) { if (_lookup != null) { if (_lookup.ContainsKey(key)) { _lookup.Remove(key); } } }
//            }
//        }
//        /// <summary>
//        /// Performs a lookup using a key (i.e. Member ID), and returns a list of all associated objects (Teacher entries)
//        /// </summary>
//        /// <param name="key"></param>
//        /// <param name="val"></param>
//        /// <returns></returns>
//        public bool PerformLookup(T1 key, ref List<T2> val)
//        {
//            if (_lookup != null)
//            {
//                lock (_lockObj) { if (_lookup != null) { if (!_lookup.TryGetValue(key, out val)) { return false; } else { return true; } } }
//            }
//            return false;
//        }
//    }
//    /// <summary>
//    /// Multiple-key caching and quick lookup.
//    /// </summary>
//    /// <typeparam name="T1">Type of key 1</typeparam>
//    /// <typeparam name="T2">Type of key 2</typeparam>
//    /// <typeparam name="T3">Type of the object being stored with keys 1 and 2</typeparam>
//    public class MultikeyLookup<T1, T2, T3> : ICrossObjectMappingBase
//    {
//        public Dictionary<T1, Dictionary<T2, T3>> _lookup = null;
//        public object _lockObj = new object();
//        internal void CheckStructure() { if (_lookup == null) { lock (_lockObj) { if (_lookup == null) _lookup = new Dictionary<T1, Dictionary<T2, T3>>(64); } } }
//        /// <summary>
//        /// Invalidate the cache
//        /// </summary>
//        public void InvalidateCache() { lock (_lockObj) { _lookup = null; } }
//        /// <summary>
//        /// Adds multiple mappings between a key and multiple values (adds many new teacher records to be associated with an existing member ID)
//        /// </summary>
//        /// <param name="key"></param>
//        /// <param name="newvals"></param>
//        public void AddOrSet(T1 key1, T2 key2, T3 obj)
//        {
//            Dictionary<T2, T3> secondkeyLookup = null;
//            T3 oldObj;
//            CheckStructure();
//            lock (_lockObj)
//            {
//                if (!_lookup.TryGetValue(key1, out secondkeyLookup))
//                {
//                    secondkeyLookup = new Dictionary<T2, T3>(32);
//                    secondkeyLookup.Add(key2, obj);
//                    _lookup.Add(key1, secondkeyLookup);
//                }
//                else if (!secondkeyLookup.TryGetValue(key2, out oldObj)) { secondkeyLookup.Add(key2, obj); }
//                else { secondkeyLookup[key2] = obj; }
//            }
//        }
//        public T3 this[T1 key1, T2 key2]
//        {
//            get { CheckStructure(); T3 obj; if (PerformLookup(key1, key2, out obj)) return obj; else return default(T3); }
//            set { CheckStructure(); AddOrSet(key1, key2, value); }
//        }
//        public bool PerformLookup(T1 key1, T2 key2, out T3 obj)
//        {
//            Dictionary<T2, T3> secondkeyLookup = null;
//            CheckStructure();
//            obj = default(T3);
//            bool fFound = false;
//            lock (_lockObj) { if (_lookup.TryGetValue(key1, out secondkeyLookup)) { if (secondkeyLookup.TryGetValue(key2, out obj)) fFound = true; } }
//            return fFound;
//        }
//        /// <summary>
//        /// Removes a lookup key from the collection
//        /// </summary>
//        /// <param name="key"></param>
//        public void Remove(T1 key1, T2 key2)
//        {
//            Dictionary<T2, T3> secondkeyLookup = null;
//            CheckStructure();
//            lock (_lockObj) { if (_lookup.TryGetValue(key1, out secondkeyLookup)) { if (secondkeyLookup.ContainsKey(key2)) secondkeyLookup.Remove(key2); } }
//        }
//    }
//    /// <summary>
//    /// Multiple-key caching and quick lookup.
//    /// </summary>
//    /// <typeparam name="T1">Type of key 1</typeparam>
//    /// <typeparam name="T2">Type of key 2</typeparam>
//    /// <typeparam name="T3">Type of the object being stored with keys 1 and 2</typeparam>
//    public class MultikeyListLookup<T1, T2, T3> : ICrossObjectMappingBase
//    {
//        public Dictionary<T1, OneToManyQuickFieldLookup<T2, T3>> _lookup = null;
//        public object _lockObj = new object();
//        internal void CheckStructure() { if (_lookup == null) { lock (_lockObj) { if (_lookup == null) _lookup = new Dictionary<T1, OneToManyQuickFieldLookup<T2, T3>>(64); } } }
//        /// <summary>
//        /// Invalidate the cache
//        /// </summary>
//        public void InvalidateCache() { lock (_lockObj) { _lookup = null; } }
//        /// <summary>
//        /// Adds multiple mappings between a key and multiple values (adds many new teacher records to be associated with an existing member ID)
//        /// </summary>
//        /// <param name="key"></param>
//        /// <param name="newvals"></param>
//        public void Set(T1 key1, T2 key2, List<T3> obj)
//        {
//            OneToManyQuickFieldLookup<T2, T3> secondkeyLookup = null;
//            List<T3> oldObj = null;
//            CheckStructure();
//            lock (_lockObj)
//            {
//                if (!_lookup.TryGetValue(key1, out secondkeyLookup))
//                {
//                    secondkeyLookup = new OneToManyQuickFieldLookup<T2, T3>();
//                    secondkeyLookup.AddMapping(key2, obj);
//                    _lookup.Add(key1, secondkeyLookup);
//                }
//                else if (!secondkeyLookup.PerformLookup(key2, ref oldObj)) { secondkeyLookup.AddMapping(key2, obj); }
//                else { secondkeyLookup.AddMapping(key2, obj); }
//            }
//        }
//        public List<T3> this[T1 key1, T2 key2]
//        {
//            get { CheckStructure(); List<T3> obj; if (PerformLookup(key1, key2, out obj)) return obj; else return new List<T3>(); }
//            set { CheckStructure(); Set(key1, key2, value); }
//        }
//        public bool PerformLookup(T1 key1, T2 key2, out List<T3> obj)
//        {
//            OneToManyQuickFieldLookup<T2, T3> secondkeyLookup = null;
//            CheckStructure();
//            obj = new List<T3>();
//            bool fFound = false;
//            lock (_lockObj)
//            {
//                if (_lookup.TryGetValue(key1, out secondkeyLookup))
//                {
//                    if (secondkeyLookup.PerformLookup(key2, ref obj)) fFound = true;
//                }
//            }
//            return fFound;
//        }
//        /// <summary>
//        /// Removes a lookup key from the collection
//        /// </summary>
//        /// <param name="key"></param>
//        public void Remove(T1 key1, T2 key2)
//        {
//            OneToManyQuickFieldLookup<T2, T3> secondkeyLookup = null;
//            CheckStructure();
//            lock (_lockObj)
//            {
//                if (_lookup.TryGetValue(key1, out secondkeyLookup))
//                {
//                    List<T3> val = null;
//                    if (secondkeyLookup.PerformLookup(key2, ref val)) secondkeyLookup.RemoveKey(key2);
//                }
//            }
//        }
//    }
//}
